-
Notifications
You must be signed in to change notification settings - Fork 1
DC-4828 --json
flag
#43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdded Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant CLI as create-db CLI
participant R as Regions API
participant C as Create DB API
U->>CLI: run create-db [--name, --region, --json]
alt JSON mode (--json)
CLI->>R: fetch regions (validate/prompt if needed)
R-->>CLI: regions list / error
CLI->>C: POST /create {name, region}
C-->>CLI: creation result
alt success
CLI-->>U: print single JSON {connectionString, directConnectionString, claimUrl, deletionDate, region, name, projectId}
else rate-limit / api error
CLI-->>U: print JSON {error, message, status/details}
end
else interactive / UI mode
CLI->>R: fetch regions (optional)
R-->>CLI: regions list / fallback
CLI->>C: POST /create {name, region}
C-->>CLI: creation result
CLI-->>U: console output, spinners, claim link
end
sequenceDiagram
autonumber
participant Client as Caller
participant Worker as create-db-worker
participant Workflow as DELETE_DB_WORKFLOW
participant Analytics as Analytics API / Env
Client->>Worker: POST /create {name, region}
Worker->>Worker: inline JSON body -> call DB API (prisma)
Worker-->>Client: return Prisma response immediately
Worker->>Worker: ctx.waitUntil(backgroundTasks())
Note over Worker: backgroundTasks parses prismaText (projectId) and runs concurrent ops
par concurrent ops
Worker->>Workflow: trigger DELETE_DB_WORKFLOW.create(...)
Worker->>Analytics: env.CREATE_DB_DATASET.writeDataPoint(...)
Workflow-->>Worker: result / error
Analytics-->>Worker: result / error
end
alt error in backgroundTasks
Worker-->>Worker: log "Error in background tasks:" + error
end
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
Deploying with
|
Status | Name | Latest Commit | Preview URL | Updated (UTC) |
---|---|---|---|---|
✅ Deployment successful! View logs |
claim-db-worker | e18cd95 | Commit Preview URL Branch Preview URL |
Aug 20 2025, 05:55 PM |
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr43
npx create-pg@pr43
npx create-postgres@$pr43 Worker URLs
|
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr43
npx create-pg@pr43
npx create-postgres@$pr43 Worker URLs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
create-db-worker/src/index.ts (3)
68-71
: Preserve optional utm_source from request bodyThe CLI now sends
utm_source
in the JSON body. You parse only{ region, name }
, so the upstream API never receivesutm_source
. Capture it here so you can forward it.Apply this diff:
- const { region, name } = body; + const { region, name, utm_source } = body; if (!region || !name) { return new Response('Missing region or name in request body', { status: 400 }); }
15-19
: Rate limiter key should consider client identity, not URLUsing
request.url
as the rate-limit key allows bypasses by varying path/query and doesn’t group abusive clients. Prefer a stable client key (e.g.,CF-Connecting-IP
), possibly combined with the route.Example:
const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown'; const route = new URL(request.url).pathname; const { success } = await env.CREATE_DB_RATE_LIMITER.limit({ key: `${ip}:${route}` });
106-108
: Consider 404 for unknown routes or include Allow header for 405Returning 405 for all fallbacks is semantically off for unknown paths. Either return 404 for unknown routes, or include an
Allow
header listing permitted methods for known routes that received the wrong method.create-db/index.js (1)
204-222
: validateRegion isn’t used in JSON flow → inconsistent JSON error semanticsYou introduced
returnJson
and throw behavior here but don’t callvalidateRegion(..., true)
in the--json
path. If a user passes an invalid region with--json
, main catches the thrown error and prints a plain text message, breaking JSON-only contracts.Apply this diff within the JSON branch to validate and return structured JSON errors:
if (flags.json) { if (chooseRegionPrompt) { region = await promptForRegion(region); } - const result = await createDatabase(name, region, true); + // Validate region with JSON-friendly error handling + try { + await validateRegion(region, true); + } catch (e) { + console.log( + JSON.stringify( + { error: "invalid_region", message: e.message }, + null, + 2 + ) + ); + process.exit(1); + } + + const result = await createDatabase(name, region, true); console.log(JSON.stringify(result, null, 2)); process.exit(0); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
.gitignore
(1 hunks)claim-db-worker/next-env.d.ts
(1 hunks)create-db-worker/src/index.ts
(2 hunks)create-db/index.js
(8 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: claim-db-worker
- GitHub Check: Workers Builds: create-db-worker
🔇 Additional comments (5)
.gitignore (1)
9-9
: LGTM:.open-next/
added to ignore listThis is an appropriate addition for OpenNext build artifacts. No concerns.
claim-db-worker/next-env.d.ts (1)
1-6
: LGTM: Standard Next.js ambient declarationsGenerated file looks correct and should remain unedited. No issues.
create-db/index.js (3)
177-202
: getRegions(returnJson): Good; throwing in JSON mode is correctThe dual-mode error handling is sensible. Keep in mind callers must catch thrown errors in JSON mode to preserve JSON-only output semantics.
If there are external callers of
getRegions(true)
, ensure they convert thrown errors to JSON responses rather than printing plain text errors.
329-339
: JSON success payload: Looks good and completeThe returned fields cover connection strings, claim URL, deletion date, region, name, and projectId. This should satisfy most machine consumers.
341-364
: JSON error payloads: Consistent with rate-limit error; goodThe
api_error
shape mirrors your 429 shape. Keep this stable for integrators.
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr43
npx create-pg@pr43
npx create-postgres@$pr43 Worker URLs
|
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr43
npx create-pg@pr43
npx create-postgres@$pr43 Worker URLs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
create-db-worker/src/index.ts (1)
15-19
: Rate limit key: consider using path + client IP to avoid easy key evasionUsing the full request URL allows query string variance to bypass rate limits. Prefer a stable key like path + client IP.
Example:
const { pathname } = new URL(request.url); const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown'; const key = `${ip}:${pathname}`; const { success } = await env.CREATE_DB_RATE_LIMITER.limit({ key });create-db/index.js (1)
180-205
: Ensure getRegions surfaces network failures in JSON mode (and doesn’t hard-exit)A network error during fetch will currently throw and be caught only by the top-level catch, which prints a human message. Wrap fetch in try/catch and honor returnJson to throw a meaningful error (non-JSON paths can still call handleError).
export async function getRegions(returnJson = false) { const url = `${CREATE_DB_WORKER_URL}/regions`; - const res = await fetch(url); + let res; + try { + res = await fetch(url); + } catch (e) { + if (returnJson) { + throw new Error( + `Network error while fetching regions: ${e?.message || e}` + ); + } + handleError("Failed to fetch regions.", e?.message || String(e)); + } if (!res.ok) { if (returnJson) { throw new Error( `Failed to fetch regions. Status: ${res.status} ${res.statusText}` ); } handleError( `Failed to fetch regions. Status: ${res.status} ${res.statusText}` ); } try { const data = await res.json(); const regions = Array.isArray(data) ? data : data.data; return regions.filter((region) => region.status === "available"); } catch (e) { if (returnJson) { throw new Error("Failed to parse JSON from /regions endpoint."); } handleError("Failed to parse JSON from /regions endpoint.", e); } }
♻️ Duplicate comments (2)
create-db-worker/src/index.ts (1)
61-82
: Forward utm_source from CLI to Prisma API (and type it)The CLI now includes utm_source in the /create request body. Forward it to the Prisma API for attribution and analytics, and extend the local body type accordingly.
- let body: { region?: string; name?: string } = {}; + let body: { region?: string; name?: string; utm_source?: string } = {}; @@ - body: JSON.stringify({ - region, - name, - }), + body: JSON.stringify({ + region, + name, + ...(body.utm_source ? { utm_source: body.utm_source } : {}), + }),create-db/index.js (1)
433-447
: Telemetry: JSON flag tracking added — looks goodhas-json-flag is captured alongside other flags; full-command and arch formatting are clean.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
create-db-worker/src/index.ts
(1 hunks)create-db/index.js
(8 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
create-db-worker/src/index.ts (2)
create-db-worker/worker-configuration.d.ts (1)
env
(6794-6794)claim-db-worker/worker-configuration.d.ts (1)
env
(6799-6799)
create-db/index.js (3)
create-db-worker/src/index.ts (1)
fetch
(13-115)claim-db-worker/src/index.ts (1)
fetch
(31-201)create-db/analytics.js (1)
analytics
(48-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: claim-db-worker
- GitHub Check: Workers Builds: create-db-worker
🔇 Additional comments (3)
create-db-worker/src/index.ts (1)
87-106
: Good restoration of background semantics with ctx.waitUntil and concurrent tasksUsing ctx.waitUntil plus Promise.all keeps the response path fast while still ensuring workflow creation and analytics run reliably in the background.
create-db/index.js (2)
75-88
: Help text: flags and examples look goodHelp now advertises --json/-j and --list-regions and adds a JSON example. This resolves the discoverability gap.
96-108
: Argument parsing: JSON flag wiring is correctallowedFlags and shorthandMap include json/j. Parsing behavior aligns with other flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (7)
create-db/index.js (7)
78-80
: Help text:--json
and--list-regions
are now documented (good catch).The help output includes both flags and a JSON example. This resolves the earlier discoverability gap.
Also applies to: 87-87
431-447
: Analytics:has-json-flag
and additional fields are wired correctly.Nice addition for observability of JSON-mode usage.
284-289
: Handle network-layer failures and preserve JSON-only output in JSON mode.A failed
fetch()
will throw and currently bubbles to the top-level catch, printing a human string. Wrap the call in try/catch and return a structured JSON error in JSON mode; keep spinner + exit flow otherwise.Apply this diff:
- const resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ region, name, utm_source: CLI_NAME }), - }); + let resp; + try { + resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ region, name, utm_source: CLI_NAME }), + }); + } catch (e) { + if (returnJson) { + return { + ok: false, + error: "network_error", + message: `Failed to reach create service: ${e?.message || String(e)}`, + }; + } + if (s) { + s.stop("Network error while creating the database. Please try again."); + } + try { + await analytics.capture("create_db:database_creation_failed", { + command: CLI_NAME, + region, + "error-type": "network_error", + }); + } catch {} + process.exit(1); + }
318-318
: Guard against non-JSON responses from the service to avoid crashes.
resp.json()
throws on HTML/text or malformed JSON. Parse from text and return a structured error in JSON mode to keep output machine-readable.Apply this diff:
- const result = await resp.json(); + let result; + let raw; + try { + raw = await resp.text(); + result = JSON.parse(raw); + } catch (e) { + if (returnJson) { + return { + ok: false, + error: "invalid_json", + message: "Unexpected response from create service.", + raw, + status: resp.status, + }; + } + if (s) { + s.stop("Unexpected response from create service."); + } + try { + await analytics.capture("create_db:database_creation_failed", { + command: CLI_NAME, + region, + "error-type": "invalid_json", + "status-code": resp.status, + }); + } catch {} + process.exit(1); + }
324-337
: Direct connection string: include optional port/database and avoid empty credentials.Port and database are omitted, and empty user/pass produce
://:@host/...
. Include:port
and db name (fallback topostgres
) and only adduser:pass@
when both exist.Apply this diff:
const directUser = directConnDetails?.user ? encodeURIComponent(directConnDetails.user) : ""; const directPass = directConnDetails?.pass ? encodeURIComponent(directConnDetails.pass) : ""; const directHost = directConnDetails?.host; - const directConn = - directConnDetails && directHost - ? `postgresql://${directUser}:${directPass}@${directHost}/postgres` - : null; + const directPort = directConnDetails?.port ? `:${directConnDetails.port}` : ""; + const directDbName = directConnDetails?.database || "postgres"; + const credentialsPart = + directConnDetails?.user && directConnDetails?.pass + ? `${directUser}:${directPass}@` + : ""; + const directConn = + directConnDetails && directHost + ? `postgresql://${credentialsPart}${directHost}${directPort}/${directDbName}` + : null;
451-453
: Skip offline preflight in JSON mode to preserve JSON-only output.
isOffline()
prints human messages and exits. Running it in JSON mode breaks the JSON contract.Apply this diff:
- if (!flags.help) { + if (!flags.help && !flags.json) { await isOffline(); }
484-505
: Ensure JSON mode always emits JSON, even on unexpected errors.Wrap the JSON-mode flow in a try/catch so any validation, network, or parsing errors print a structured JSON object and a non-zero exit.
Apply this diff:
- if (flags.json) { - if (chooseRegionPrompt) { - region = await promptForRegion(region); - } - - try { - await validateRegion(region, true); - } catch (e) { - console.log( - JSON.stringify( - { error: "invalid_region", message: e.message }, - null, - 2 - ) - ); - process.exit(1); - } - - const result = await createDatabase(name, region, true); - console.log(JSON.stringify(result, null, 2)); - process.exit(0); - } + if (flags.json) { + try { + if (chooseRegionPrompt) { + region = await promptForRegion(region); + } else { + await validateRegion(region, true); + } + const result = await createDatabase(name, region, true); + console.log(JSON.stringify(result, null, 2)); + process.exit(0); + } catch (e) { + console.log( + JSON.stringify( + { error: "cli_error", message: e?.message || String(e) }, + null, + 2 + ) + ); + process.exit(1); + } + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
create-db/index.js
(8 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
create-db/index.js (3)
create-db-worker/src/index.ts (1)
fetch
(13-115)claim-db-worker/src/index.ts (1)
fetch
(31-201)create-db/analytics.js (1)
analytics
(48-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: claim-db-worker
- GitHub Check: Workers Builds: create-db-worker
🔇 Additional comments (3)
create-db/index.js (3)
96-102
: CLI flag plumbing for--json
/-j
and--list-regions
is correct.
allowedFlags
andshorthandMap
cover all new flags as expected.Also applies to: 107-107
185-189
: JSON-mode error propagation from getRegions/validateRegion looks good.Throwing in
returnJson
mode lets the caller format a machine-readable error. This aligns with the JSON-only contract.Also applies to: 200-203
270-273
: Event enrichment: selection-method "interactive" looks good.This clarifies how the region was chosen.
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr43
npx create-pg@pr43
npx create-postgres@$pr43 Worker URLs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
create-db/index.js (1)
24-26
: handleError “extra” parameter is mislabeled in output; pass error details or rename labelThe current handler prints extra under “Available regions:” which is misleading when the “extra” is an error message or object. Either pass e?.message or change the handleError formatter to label it “Details:”.
Apply these diffs to pass messages:
- handleError("Failed to fetch regions.", e); + handleError("Failed to fetch regions.", e?.message || String(e));- handleError("Failed to parse JSON from /regions endpoint.", e); + handleError("Failed to parse JSON from /regions endpoint.", e?.message || String(e));- handleError("Failed to fetch regions.", e); + handleError("Failed to fetch regions.", e?.message || String(e));And consider updating handleError (outside the selected ranges):
function handleError(message, details = "") { console.error( "\n" + chalk.red.bold("✖ An error occurred!") + "\n\n" + chalk.white("Message: ") + chalk.yellow(message) + (details ? "\n" + chalk.white("Details: ") + chalk.gray(details) : "") + "\n" ); process.exit(1); }Also applies to: 200-203, 246-248
♻️ Duplicate comments (8)
create-db/index.js (8)
78-80
: Help text: flags and examples updated correctlyThe help now advertises --json/-j and --list-regions, plus a JSON example. This resolves prior discoverability concerns.
Also applies to: 87-87
96-102
: Args parsing: allowed flags and shorthand map are consistent with help--json is included in allowedFlags and mapped to -j. LGTM.
Also applies to: 107-107
459-477
: Analytics: has-json-flag captured; payload is cleanNice addition and tidy formatting.
481-483
: Skip offline preflight in JSON modeThis preserves JSON-only output. Good.
290-298
: Standardize JSON errors with ok: falseReturn objects in JSON mode should include ok: false for easy client branching.
Apply this diff:
if (returnJson) { return { + ok: false, error: "rate_limit_exceeded", message: "We're experiencing a high volume of requests. Please try again later.", status: 429, }; }
Also applies to: 300-316
372-382
: Success JSON: add ok: true for symmetry with errorsMakes client logic simpler.
Apply this diff:
if (returnJson && !result.error) { return { + ok: true, connectionString: prismaConn, directConnectionString: directConn, claimUrl: claimUrl, deletionDate: expiryDate.toISOString(), region: database?.region?.id || region, name: database?.name, projectId: projectId, }; }
385-391
: API error JSON: add ok: falseConsistent with success response.
Apply this diff:
if (result.error) { if (returnJson) { return { + ok: false, error: "api_error", message: result.error.message || "Unknown error", details: result.error, }; }
284-289
: createDatabase: catch network errors around fetch for structured JSON and clean UIA network failure will currently bubble (caught at the top-level). In JSON mode that becomes { error: "cli_error" }, but we lose error-type specificity and spinner won’t stop in human mode. Catch here to preserve behavior in both modes and tag analytics.
Apply this diff:
- const resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ region, name, utm_source: CLI_NAME }), - }); + let resp; + try { + resp = await fetch(`${CREATE_DB_WORKER_URL}/create`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ region, name, utm_source: CLI_NAME }), + }); + } catch (e) { + if (returnJson) { + return { + ok: false, + error: "network_error", + message: `Failed to reach create service: ${e?.message || String(e)}`, + }; + } + if (s) { + s.stop("Network error while creating the database. Please try again."); + } + try { + await analytics.capture("create_db:database_creation_failed", { + command: CLI_NAME, + region, + "error-type": "network_error", + }); + } catch {} + process.exit(1); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
create-db/index.js
(8 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
create-db/index.js (3)
create-db-worker/src/index.ts (1)
fetch
(13-115)claim-db-worker/src/index.ts (1)
fetch
(31-201)create-db/analytics.js (1)
analytics
(48-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Workers Builds: create-db-worker
- GitHub Check: Workers Builds: claim-db-worker
🔇 Additional comments (3)
create-db/index.js (3)
207-216
: validateRegion: JSON-mode behavior is correctThrows in JSON mode with a clear message; non-JSON still uses handleError. Good separation.
267-272
: Analytics: selection-method tagging looks goodConsistent "interactive" tag for prompt-based selection. LGTM.
277-283
: Spinner gating on returnJsonNice separation: spinner only in interactive/human mode.
Summary by CodeRabbit
New Features
Chores